from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, ElementClickInterceptedException
from config import CTYUN_USERNAME, CTYUN_PASSWORD
from selenium.webdriver.firefox.options import Options as FirefoxOptions
import logging
import json
from utils.logger import logger


def create_remote_driver():
    """创建远程 WebDriver"""
    options = Options()
    options.add_argument('--no-sandbox')
    # options.add_argument('--headless')
    options.add_argument('--disable-dev-shm-usage')
    options.add_argument('--start-maximized')  # 窗口最大化
    options.add_argument('--disable-blink-features=AutomationControlled')  # 禁用自动化标识
    
    # 禁用密码保存提示
    prefs = {
        "credentials_enable_service": False,
        "profile.password_manager_enabled": False,
        "profile.default_content_setting_values.notifications": 2  # 同时禁用通知提示
    }
    options.add_experimental_option("prefs", prefs)
    
    # 移除 webdriver 特征
    options.add_experimental_option("excludeSwitches", ["enable-automation"])
    options.add_experimental_option('useAutomationExtension', False)
    
    # 连接到远程 Selenium Grid
    driver = webdriver.Remote(
        command_executor='http://1.92.153.12:15255/wd/hub',
        options=options
    )
    
    # 执行 JavaScript 来移除 webdriver 标记
    driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
    
    return driver

def create_local_driver():
    """创建本地 WebDriver"""
    options = Options()
    options.add_argument('--no-sandbox')
    # options.add_argument('--headless')
    options.add_argument('--disable-dev-shm-usage')
    options.add_argument('--start-maximized')  # 窗口最大化
    options.add_argument('--disable-blink-features=AutomationControlled')  # 禁用自动化标识
    
    # 禁用密码保存提示
    prefs = {
        "credentials_enable_service": False,
        "profile.password_manager_enabled": False,
        "profile.default_content_setting_values.notifications": 2  # 同时禁用通知提示
    }
    options.add_experimental_option("prefs", prefs)
    
    # 移除 webdriver 特征
    options.add_experimental_option("excludeSwitches", ["enable-automation"])
    options.add_experimental_option('useAutomationExtension', False)
    
    # 创建本地 Chrome WebDriver
    driver = webdriver.Chrome(options=options)
    
    # 执行 JavaScript 来移除 webdriver 标记
    driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
    
    return driver

def create_local_firefox_driver():
    """创建本地 Firefox WebDriver"""
    options = FirefoxOptions()
    options.add_argument('--no-sandbox')
    # options.add_argument('--headless')
    options.add_argument('--start-maximized')  # 窗口最大化
    
    # 禁用自动化标识
    options.set_preference('dom.webdriver.enabled', False)
    options.set_preference('useAutomationExtension', False)
    
    # 禁用密码保存和通知提示
    options.set_preference('signon.rememberSignons', False)
    options.set_preference('dom.push.enabled', False)
    options.set_preference('dom.webnotifications.enabled', False)
    
    # 创建本地 Firefox WebDriver
    driver = webdriver.Firefox(options=options)
    
    # 执行 JavaScript 来移除 webdriver 标记
    driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
    
    return driver

def wait_and_click(wait, xpath):
    """等待元素可点击并执行点击操作"""
    element = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
    element.click()
    return element

def get_login_info():
    try:
        # 初始化本地 Firefox WebDriver
        driver = create_local_firefox_driver()
        logger.info("成功创建本地 Firefox WebDriver")
        
        # 设置等待对象，超时时间设为 20 秒
        wait = WebDriverWait(driver, 20)
        
        # 访问登录页面
        driver.get('https://www.ctyun.cn/h5/auth/login')
        logger.info("访问登录页面")
        
        # 点击账号登录标签
        try:
            wait_and_click(wait, "//div[contains(@class, 'tabs-item') and text()='账号登录']")
            logger.info("点击账号登录标签")
        except TimeoutException:
            logger.error("无法找到账号登录标签")
            raise
        
        # 输入账号
        username_input = wait.until(
            EC.presence_of_element_located((By.XPATH, "//input[@placeholder='登录名/邮箱']"))
        )
        username_input.clear()
        username_input.send_keys(CTYUN_USERNAME)
        logger.info("输入用户名")
        
        # 输入密码
        password_input = wait.until(
            EC.presence_of_element_located((By.XPATH, "//input[@placeholder='请输入密码']"))
        )
        password_input.clear()
        password_input.send_keys(CTYUN_PASSWORD)
        logger.info("输入密码")
        
        # 勾选同意协议
        try:
            checkbox = wait.until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, ".el-checkbox"))
            )
            checkbox.click()
            logger.info("勾选同意协议")
        except Exception as e:
            logger.error(f"无法点击复选框: {str(e)}")
            raise
        
        # 点击登录按钮
        wait_and_click(wait, "//button[contains(@class, 'el-button')]")
        logger.info("点击登录按钮")
        # 等待登录成功
        wait.until(lambda driver: "login" not in driver.current_url)
        logger.info("登录成功")
        
        # 访问容器镜像服务页面
        driver.get('https://console2.ctyun.cn/swr/?region=cn-hncs1#/swr/dashboard?regionid=cn-hncs1')
        logger.info("访问容器镜像服务页面")
        
        # 等待并点击"登录指令"按钮
        login_cmd_button = wait.until(
            EC.element_to_be_clickable((By.XPATH, 
                "//button[contains(@class, 'ti3-btn-large') and contains(text(), '登录指令')]"
            ))
        )
        login_cmd_button.click()
        logger.info("点击登录指令按钮")
        
        # 获取登录指令
        login_command = wait.until(
            EC.presence_of_element_located((By.XPATH, 
                "//pre/code//p[contains(text(), 'docker login')]"
            ))
        ).text.strip()
        
        # 获取过期时间
        expiry_time = wait.until(
            EC.presence_of_element_located((By.XPATH, 
                "//span[contains(@class, 'lego-text-tip')]"
            ))
        ).text
        
        # 保存登录信息
        with open("docker_login_info.txt", "w", encoding="utf-8") as f:
            f.write(f"登录指令: {login_command}\n")
            f.write(f"过期时间: {expiry_time}\n")
        logger.info("保存登录信息到文件")
        
        # 关闭登录指令模态框
        close_button = wait.until(
            EC.element_to_be_clickable((By.XPATH, 
                "//button[contains(@class, 'ti3-btn-middle') and contains(text(), '关闭')]"
            ))
        )
        close_button.click()
        logger.info("关闭登录指令模态框")
        
        # 等待模态框消失
        wait.until(
            EC.invisibility_of_element_located((By.CSS_SELECTOR, 
                "app-login-command"
            ))
        )
        logger.info("登录指令模态框已关闭")
        
        # 等待并点击"我的镜像"链接
        my_images_link = wait.until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, 
                "a[href='#/swr/warehouse']"
            ))
        )
        my_images_link.click()
        logger.info("点击我的镜像链接")
        
        # 等待表格加载
        wait.until(
            EC.presence_of_element_located((By.CSS_SELECTOR, "ag-grid-angular"))
        )
        logger.info("镜像列表加载完成")
        
        # 等待表格内容加载完成
        wait.until(
            EC.presence_of_element_located((By.CSS_SELECTOR, ".ag-center-cols-container"))
        )
        
        # 获取所有镜像行
        image_rows = driver.find_elements(By.CSS_SELECTOR, ".ag-center-cols-container .ag-row")
        logger.info(f"找到 {len(image_rows)} 个镜像")
        
        # 构建镜像数据
        image_data = []
        for row in image_rows:
            try:
                # 等待单元格加载
                wait.until(
                    EC.presence_of_element_located((By.CSS_SELECTOR, ".ag-cell"))
                )
                
                name = row.find_element(By.CSS_SELECTOR, ".ag-cell[col-id='name'] a").text.strip()
                namespace = row.find_element(By.CSS_SELECTOR, ".ag-cell[col-id='namespace'] span").text.strip()
                is_public = row.find_element(By.CSS_SELECTOR, ".ag-cell[col-id='is_public'] span.lego-tag").text.strip()
                tag_count = row.find_element(By.CSS_SELECTOR, ".ag-cell[col-id='tag_count'] div").text.strip()
                updated_time = row.find_element(By.CSS_SELECTOR, ".ag-cell[col-id='updated_time'] span").text.strip()
                
                image_data.append({
                    "name": name,
                    "namespace": namespace,
                    "is_public": is_public,
                    "tag_count": int(tag_count),
                    "updated_time": updated_time
                })
                logger.debug(f"成功解析镜像: {name}")
                
            except Exception as e:
                logger.error(f"解析镜像行时发生错误: {str(e)}")
        
        logger.info(f"成功获取 {len(image_data)} 个镜像信息")
        
        # 保存镜像列表数据
        with open("image_list.json", "w", encoding="utf-8") as f:
            json.dump(image_data, f, indent=2, ensure_ascii=False)
        logger.info("镜像列表数据已保存到 image_list.json")
        
        return True
        
    except Exception as e:
        logger.error(f"获取登录信息时发生错误: {str(e)}")
        return False
        
    finally:
        driver.quit()
        logger.info("关闭浏览器")

if __name__ == "__main__":
    if get_login_info():
        logger.info("成功获取登录信息")
    else:
        logger.error("获取登录信息失败")